﻿using CMS.Util;
using Newtonsoft.Json;
using System;

namespace CMS.Infos
{
    public class CourseRoom : ICloneable, IAssignable
    {
        [JsonProperty(PropertyName = "id")]
        public int ID { get; set; }

        [JsonProperty(PropertyName = "name")]
        public string Name { get; set; }

        [JsonProperty(PropertyName = "teacher")]
        public string Teacher { get; set; }

        [JsonProperty(PropertyName = "class_name")]
        public string ClassName { get; set; }

        [JsonProperty(PropertyName = "term_id")]
        public int TermID { get; set; }

        /// <summary>
        /// 从1-7分别表示星期一到星期五
        /// </summary>
        [JsonProperty(PropertyName = "week")]
        public ushort Week { get; set; }

        [JsonProperty(PropertyName = "class_week")]
        public uint ClassWeekRaw
        {
            get => _ClassWeekRaw; set
            {
                _ClassWeek = null;
                _ClassWeekRaw = value;
            }
        }


        [JsonProperty(PropertyName = "class_time")]
        public uint ClassTimeRaw
        {
            get => _ClassTimeRaw; set
            {
                _ClassTimeRaw = value;
                _ClassTime = null;
                _StartTime = null;
                _TimeSpan = null;
            }
        }


        [JsonProperty(PropertyName = "room")]
        public string Room { get; set; }


        [JsonProperty(PropertyName = "student_count")]
        public int StudentCount { get; set; }


        #region 内部缓存字段
        [JsonIgnore]
        private uint _ClassWeekRaw;

        [JsonIgnore]
        private uint _ClassTimeRaw;

        [JsonIgnore]
        private string _ClassWeek;

        [JsonIgnore]
        private string _ClassTime;

        [JsonIgnore]
        private int? _StartTime;

        [JsonIgnore]
        private int? _TimeSpan;


        #endregion

        #region 拓展字段(方便程序使用)
        [JsonIgnore]
        public string ClassWeek
        {
            get
            {
                if (_ClassWeek == null)
                {
                    _ClassWeek = Utils.ConvertValue(_ClassWeekRaw);
                }
                return _ClassWeek;
            }
            set => ClassWeekRaw = Utils.ConvertValue(value);
        }

        [JsonIgnore]
        public string ClassTime
        {
            get
            {
                if (_ClassTime == null)
                {
                    _ClassTime = Utils.ConvertValue(_ClassTimeRaw);
                }
                return _ClassTime;
            }
            set => ClassTimeRaw = Utils.ConvertValue(value);
        }


        [JsonIgnore]
        public int StartTime
        {
            get
            {
                if (_StartTime == null)
                {
                    _StartTime = Utils.CalcTimeStart(_ClassTimeRaw) + 1;
                }
                return _StartTime.Value;
            }
        }

        [JsonIgnore]
        public int TimeSpan
        {
            get
            {
                if (_TimeSpan == null)
                {
                    _TimeSpan = Utils.CalcTimeSpan(_ClassTimeRaw, 14);
                }
                return _TimeSpan.Value;
            }
        }

        [JsonIgnore]
        public object Tag { get; set; }

        #endregion



        #region 通用性重写
        public override int GetHashCode()
        {
            return (int)((Name?.GetHashCode() ?? 0) ^
                (Room?.GetHashCode() ?? 0) ^
                (Teacher?.GetHashCode() ?? 0) ^
                (ClassName?.GetHashCode() ?? 0) ^
                TermID ^
                Week ^
                ClassWeekRaw ^
                ClassTimeRaw ^
                StudentCount
                );
        }

        public override bool Equals(object obj)
        {
            if (obj is CourseRoom cr)
            {
                return Equals(cr.Name, Name) &&
                     Equals(cr.Room, Room) &&
                     Equals(cr.Teacher, Teacher) &&
                     Equals(cr.ClassName, ClassName) &&
                     cr.TermID == TermID &&
                     cr.Week == Week &&
                     cr.ClassWeekRaw == ClassWeekRaw &&
                     cr.ClassTimeRaw == ClassTimeRaw &&
                     cr.StudentCount == StudentCount;
            }
            else
            {
                return false;
            }
        }

        public override string ToString()
        {
            return $"{Name} {{{ClassWeek}周 第{ClassTime}节 星期{Week}}}";
        }

        public object Clone()
        {
            return new CourseRoom()
            {
                ID = ID,
                Name = Name,
                Week = Week,
                TermID = TermID,
                Room = Room,
                ClassName = ClassName,
                ClassWeekRaw = ClassWeekRaw,
                ClassTimeRaw = ClassTimeRaw,
                Teacher = Teacher,
                StudentCount = StudentCount
            };
        }

        public object Assign(object src)
        {
            if (src is CourseRoom src2)
            {
                ID = src2.ID;
                Name = src2.Name;
                Week = src2.Week;
                TermID = src2.TermID;
                Room = src2.Room;
                ClassName = src2.ClassName;
                ClassWeekRaw = src2.ClassWeekRaw;
                ClassTimeRaw = src2.ClassTimeRaw;
                Teacher = src2.Teacher;
                StudentCount = src2.StudentCount;
            }
            else
            {
                throw new ArgumentException();
            }
            return this;
        }

        #endregion
    }
}
